using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Data;
using System.Data.SqlClient;

namespace UDS.Management.Data.Package
{
    public class SqlCommandReader
    {
        private TextReader m_reader;
        private long m_beginLineNo;
        private long m_endLineNo;

        /// <summary>
        /// The regular expression that decides whether a given line of text is a terminating 'GO' line in the
        /// sql script.  It allows for any number of spaces at the beginning and end.
        /// </summary>
        private static readonly Regex GoRegex = new Regex(@"^[\s]*GO[\s]*$", RegexOptions.IgnoreCase | RegexOptions.Compiled);

        public SqlCommandReader(string path)
        {
            if (!File.Exists(path))
            {
                throw new ArgumentException(String.Format("File {0} does not exist", path), "path");
            }
            m_reader = new StreamReader(path);
            m_beginLineNo = 0;
            m_endLineNo = 0;
        }

        public SqlCommandReader(TextReader reader)
        {
            m_reader = reader;
            m_beginLineNo = 0;
            m_endLineNo = 0;
        }

        public long BeginLineNumber
        {
            get
            {
                return m_beginLineNo;
            }
        }

        public long EndingLineNumber
        {
            get { return m_endLineNo; }
        }

        public string ReadCommand()
        {
            m_beginLineNo = m_endLineNo + 1;
            StringBuilder command = new StringBuilder();
            string currentLine;
            bool begin = true;
            while ((currentLine = m_reader.ReadLine()) != null)
            {
                m_endLineNo++;
                if (begin && currentLine.Trim() == String.Empty)
                {
                    // skip blank lines or whitespaces
                    m_beginLineNo++;
                }
                else
                {
                    if (IsGoLine(currentLine))
                    {
                        // Skip empty GO block also
                        if (!begin)
                        {
                            break;
                        }
                    }
                    else
                    {
                        begin = false;
                        command.AppendLine(currentLine);
                    }
                }
            }
            if (command.Length > 0)
            {
                return command.ToString();
            }
            else
            {
                return null;
            }
        }

        public void ResetContentCounters()
        {
            m_beginLineNo = 0;
            m_endLineNo = 0;
        }

        public SqlCommand ReadSqlCommand()
        {
            string command = ReadCommand();
            if (command != null)
            {
                SqlCommand cmd = new SqlCommand(command);
                cmd.CommandType = CommandType.Text;
                return cmd;
            }
            return null;
        }

        public void Close()
        {
            if (m_reader != null)
            {
                m_reader.Close();
            }
        }

        /// <summary>
        /// Determine if the line of text is a delmiting GO line of sql script
        /// </summary>
        /// <param name="line">The line to check</param>
        /// <returns>True if the line is a GO line, false otherwise</returns>
        private static bool IsGoLine(string line)
        {
            // Decide if the line matches
            return GoRegex.IsMatch(line);
        }

    }
}
